package com.youlu.campus.admin.zm.task;

import com.google.common.collect.Lists;
import com.youlu.campus.admin.zm.entity.SimpleOrderInfo;
import com.youlu.campus.admin.zm.service.AsyncZmService;
import com.youlu.campus.admin.zm.utils.ZmMenuUtils;
import com.youlu.campus.admin.zm.utils.ZmUtils;
import com.youlu.campus.base.sys.DelayMsgGray;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;


import java.util.Date;
import java.util.Map;
import java.util.Random;
import java.util.Set;

/**
 * @author : [dengbo]
 * @className : RedisDelayQueue
 * @description : [延迟队列]
 * @createTime : [2022/11/13 15:20]
 */
@Slf4j
@Service
public class RedisDelayQueue {
    private static final String ZM_MSG = "zm.flow.msg.list";

    @Autowired
    private AsyncZmService asyncZmService;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 设置延迟消息
     *
     * @param delayTask
     */
    public boolean addRandomDelayTask(DelayTask delayTask) {
        DelayMsgGray delayMsgGray = asyncZmService.getDelayMsgGray();
        Random random = new Random();
        long delayTime = delayMsgGray.getDefaultDelayTime() + random.nextInt(delayMsgGray.getMaxDelayTime() - delayMsgGray.getDefaultDelayTime() + 1);
        // 使用RedisTemplate操作ZSet添加元素
        Boolean re = redisTemplate.opsForZSet().add(ZM_MSG, delayTask.getTaskId(), System.currentTimeMillis() + delayTime);
        log.info("taskId:{} add delay task result:{}", delayTask.getTaskId(), re);
        return re != null && re;
    }


    /**
     * 监听延迟消息
     */
    public void listenDelayLoop() {
        // 获取时间当前时间之内获取的消息
        try {
            DelayMsgGray delayMsgGray = asyncZmService.getDelayMsgGray();
            if (delayMsgGray == null) {
                return;
            }
            Thread.sleep(delayMsgGray.getSleepTime());

            // 使用RedisTemplate查询指定分数范围内的ZSet元素
            Set<String> rank = redisTemplate.opsForZSet().rangeByScore(
                    ZM_MSG,
                    0,
                    System.currentTimeMillis(),
                    0,
                    delayMsgGray.getDealMsgNum()
            );

            if (CollectionUtils.isEmpty(rank)) {
                return;
            }

            // 获取ZSet总元素数
            Long total = redisTemplate.opsForZSet().size(ZM_MSG);
            log.info("zm.flow.msg.lis total:{},dealNum:{}", total, delayMsgGray.getDealMsgNum());

            for (String taskId : rank) {
                // 移除ZSet中的元素
                Long removeRe = redisTemplate.opsForZSet().remove(ZM_MSG, taskId);
                log.info("taskId:{} remove task result:{}", taskId, removeRe);

                if (removeRe != null && removeRe == 1) {
                    // 处理任务（业务逻辑不变）
                    ZmUtils.ZmOpFlowInfo req = ZmUtils.getZmOpFlowInfo(taskId);
                    Map<String, String> cacheResult = asyncZmService.getFlowCache(req.getOpenid(), req.getFlowId());
                    if (MapUtils.isEmpty(cacheResult)) {
                        asyncZmService.sendOneMsg(req.getOpenid(), req.getFlowId(), ZmMenuUtils.getTimeOutMsg());
                        continue;
                    }
                    String orderNo = cacheResult.get("orderNo");
                    SimpleOrderInfo orderInfo = asyncZmService.getSimpleOrderInfo(orderNo);
                    if (orderInfo == null) {
                        //同步发送一条消息
                        asyncZmService.sendOneMsg(req.getOpenid(), req.getFlowId(), ZmMenuUtils.getRefundOrderNotExistMsg());
                        // 发送结束流程消息
                        asyncZmService.sendAsyncOneMsg(req.getOpenid(), req.getFlowId(), ZmMenuUtils.getFlowEndMsg(), true, true);
                        continue;
                    }
                    Integer itemType = Integer.valueOf(cacheResult.get("itemType"));
                    String logisticsCompanys = cacheResult.get("logisticsCompanys");
                    String logNos = cacheResult.get("logisticsNos");
                    String userName = StringUtils.isBlank(orderInfo.getName()) ? "" : orderInfo.getName();
                    String orderStatus = orderInfo.getStatus();
                    log.info("async user openid:{} order status:{}", req.getOpenid(), orderStatus);
                    // 未支付
                    if ("0".equals(orderStatus)) {
                        //同步发送一条消息
                        asyncZmService.sendOneMsg(req.getOpenid(), req.getFlowId(), ZmMenuUtils.getNotPayEndMsg(userName));
                        // 发送结束流程消息
                        asyncZmService.sendAsyncOneMsg(req.getOpenid(), req.getFlowId(), ZmMenuUtils.getFlowEndMsg(), true, true);
                        continue;
                    }
                    // 订单退款
                    if (Lists.newArrayList("6", "9").contains(orderStatus)) {
                        //同步发送一条消息
                        asyncZmService.sendOneMsg(req.getOpenid(), req.getFlowId(), ZmMenuUtils.getAlreadyRefundMsg(orderInfo.getRefundStatus(), userName));
                        // 发送结束流程消息
                        asyncZmService.sendAsyncOneMsg(req.getOpenid(), req.getFlowId(), ZmMenuUtils.getFlowEndMsg(), true, true);
                        continue;
                    }
                    // 已经发货
                    if ("4".equals(orderStatus)) {
                        asyncZmService.sendOneMsg(req.getOpenid(), req.getFlowId(), ZmMenuUtils.getDeliveryNewMsg(itemType, userName, logisticsCompanys, logNos));
                        asyncZmService.sendAsyncOneMsg(req.getOpenid(), req.getFlowId(), ZmMenuUtils.getRefundFlowEndWithTransferMsg(), true, true);
                        continue;
                    }
                    // 未发货
                    Date payTime = orderInfo.getPayTime();
                    long hour = (System.currentTimeMillis() - payTime.getTime()) / 1000 / 3600;
                    log.info("async user openid:{} current time to pay time hour:{}", req.getOpenid(), hour);
                    // 12小时之内
                    if (hour < 12) {
                        asyncZmService.sendAsyncOneMsg(req.getOpenid(), req.getFlowId(), ZmMenuUtils.getNotDeliveryLess12Msg(itemType, userName));
                        continue;
                    }
                    // 12 小时之后
                    asyncZmService.sendOneMsg(req.getOpenid(), req.getFlowId(), ZmMenuUtils.getNotDeliveryMore12NewResponse(itemType, userName));
                    asyncZmService.sendAsyncOneMsg(req.getOpenid(), req.getFlowId(), ZmMenuUtils.getRefundFlowEndWithTransferMsg(), true, true);
                }
            }
        } catch (Exception e) {
            log.error("listenDelayLoop error", e);
        }
    }
}
